Skip to content

feat(signal-notifier): remove V/OI gate, widen moneyness cap to 0.13, score-led ranking#29

Open
DevDizzle wants to merge 25 commits into
masterfrom
gate-changes-2026-06-02
Open

feat(signal-notifier): remove V/OI gate, widen moneyness cap to 0.13, score-led ranking#29
DevDizzle wants to merge 25 commits into
masterfrom
gate-changes-2026-06-02

Conversation

@DevDizzle

Copy link
Copy Markdown
Owner

Three owner-directed signal-quality changes to the signal-notifier STRICT selection path, driven by the first leak-free realized-option-PnL backtest (1,375 fills — backfilled full 3-day option minute bars + replayed the exact +80/−60/trail bracket). No trader-mechanics change; every tradeability gate retained. All three are one-line reverts and cleared gammarips-review. Already live in prod (signal-notifier 00028-pm7).

Changes

  • Remove V/OI > 2 gate. Realized PnL: dropped ~55–63% of real winners for precision lift statistically ≤ 0 (90% CI [−0.061, −0.001]), not fillability-confounded, stable across chronological halves. Folklore gate; main cause of picker-slate starvation (~2 candidates/day).
  • Score-led STRICT ORDER BY (overnight_score, recommended_oi, spread, ticker) — now identical to FALLBACK. V/OI is a poor filter and a poor ranking key. Supersedes the 2026-05-01 V/OI-DESC primary.
  • Widen moneyness cap 0.10 → 0.13 (STRICT only; FALLBACK_MONEYNESS_MAX decoupled + pinned at 0.10 — prior = MONEYNESS_MAX would have leaked deep-OTM onto low-conviction skip days). Realized PnL: 10–13% increment +8.9% (CI [+.014, +.163]); (0.14, 0.15] bin toxic so cap stops at 0.13. Mechanism correction, not a literature reversal — the deep-OTM-cliff lit is hold-to-expiry; our 3-day bracket is not that trade.

Caveats / monitoring

  • Moneyness widening rests on thin, single-regime evidence and can't be cost-validated in a paper system — reversible (MONEYNESS_MAX → 0.10). Monitor the 10–13% cohort: ledger scan_date ≥ 2026-06-02 ⨝ enriched on (ticker, scan_date) WHERE moneyness_pct ∈ (0.10, 0.13].
  • Slate size should climb; INVALID_LIQUIDITY rate should hold (fillability gates kept).

Research included (backtesting_and_research/)

  • Realized-PnL backtest infra (fetch_hold_window_bars.py, realized_option_label.py, gate_recall.py, gate_validity_checks.py, moneyness_band_study.py).
  • Exit-design study FALSIFIED the external deep-research "drop the −60% premium stop" claim — removing it = zero EV change, just fatter tails (the wick-out is a hold-to-expiry artifact). Kept the stop.
  • Sweep/ISO detection (H20) parked — Polygon taxonomy exists but /v3/trades is 403 on our tier; revisit post-upgrade once EV is proven.

Decision docs

  • docs/DECISIONS/2026-06-02-voi-gate-relaxation-proposal.md
  • docs/DECISIONS/2026-06-02-moneyness-cap-widen-to-13.md

Docs synced: CLAUDE.md, TRADING-STRATEGY.md, CHEAT-SHEET.md, INTELLIGENCE_BRIEF.md (H16–H21), NEXT_SESSION_PROMPT.md.

🤖 Generated with Claude Code

DevDizzle and others added 25 commits June 1, 2026 19:33
Isolated generate_per_signal_seo() Gemini call (SEO_PROMPT_VERSION=
signal_seo_v1) writes seoMetadata onto overnight_signals/{date}_{ticker}
docs for the top-10 candidates via Stage 5 (.update, non-blocking,
deterministic per-ticker fallback). Kept fully separate from the report
markdown call so report_md / the V5.4 ranker is byte-for-byte unaffected.
Closes the per-ticker SEO gap (pages were falling back to thin
'{TICKER} Signal' titles). gammarips-review: SHIP.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…failures

Publisher could not resolve a slug — the planner embeds schedule_slot nested
in post_outline (a JSON string under output_key), but Publisher read top-level
state['schedule_slot'] (never set) and outline['slug'] (wrong nesting), so
slug='' and publish_to_firestore('') returned error while /generate still
returned 200 — blog_posts stayed empty.

- Parse the writer's YAML front matter (authoritative: slug/title/description/
  keywords/cta; schedule row lacks description) as primary metadata source;
  strip it from the stored markdown body so posts render cleanly.
- Loud ERROR log on unresolved slug; /generate now 500s on error/rejected so
  failures surface and Cloud Scheduler retries.

Verified: real /generate published blog_posts/why-uoa-is-mostly-noise.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Front-matter parsing is the primary metadata source but the LLM occasionally
emits a body whose front-matter block isn't at position 0, so it fails to
parse; combined with the nested-in-outline schedule_slot (not in top-level
state), slug resolved to '' and publish 500'd. Add a last-resort read from
tools.fetch_next_schedule_slot() — in the cron drain the first pending row is
the current post; manual retries resolve slug from state['slug'] earlier and
never reach this path. Uses the existing plain tool fn (no ADK ToolContext).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… score-led ranking

Three owner-directed signal-quality changes to the STRICT selection path,
driven by the first leak-free realized-option-PnL backtest (1,375 fills;
backfilled full 3-day option minute bars + replayed the exact +80/-60/trail
bracket). No trader-mechanics change; every tradeability gate retained.

- Remove `V/OI > 2` conviction gate. Realized PnL: dropped ~55-63% of real
  option winners for precision lift statistically <= 0 (90% CI [-0.061,-0.001]),
  not fillability-confounded, stable across chronological halves. Folklore gate
  that was the main cause of picker-slate starvation (~2 candidates/day).
- Re-rank STRICT ORDER BY from directional-V/OI-DESC to overnight_score-led
  (overnight_score, recommended_oi, spread, ticker) -- now identical to FALLBACK.
  V/OI is a poor filter and a poor ranking key. Supersedes the 2026-05-01 primary.
- Widen moneyness cap 0.10 -> 0.13 (STRICT only; FALLBACK_MONEYNESS_MAX decoupled
  and pinned at 0.10 -- prior `= MONEYNESS_MAX` would have leaked deep-OTM onto
  low-conviction skip days). Realized PnL: 10-13% increment +8.9% (CI
  [+.014,+.163]); the (0.14,0.15] bin is toxic so cap stops at 0.13. Mechanism
  correction, not a literature reversal: the deep-OTM-cliff lit is hold-to-expiry,
  our 3-day bracket is not that trade. Thin/single-regime -- reversible, monitored.

All three cleared gammarips-review. Decision docs:
docs/DECISIONS/2026-06-02-voi-gate-relaxation-proposal.md,
docs/DECISIONS/2026-06-02-moneyness-cap-widen-to-13.md.

Research (backtesting_and_research/): exit-design study FALSIFIED the deep-research
"drop the -60% premium stop" claim (removing it = zero EV change, just fatter
tails -- the wick-out is a hold-to-expiry artifact); sweep/ISO detection (H20)
parked, blocked on Polygon data tier. Brief: H16-H21. Docs synced (CLAUDE.md,
TRADING-STRATEGY.md, CHEAT-SHEET.md, INTELLIGENCE_BRIEF.md, NEXT_SESSION_PROMPT.md).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Captures the 2026-06-03 sector-persistence + webapp internal-linking work:
enrichment now writes sector/industry to overnight_signals_enriched + the
Firestore signal doc; the webapp ranks same-sector related signals. The columns
are NULLABLE and NON-GATING (read by no gate/WHERE/ranking).

- DATA-CONTRACTS.md: sector/industry metadata columns entry
- DECISIONS/2026-06-03-sector-persistence-and-webapp-internal-linking.md (new)

The enrichment code hunks for this ship in the following commit (same file as
the FRED work, unavoidably entangled in one working tree).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…e gate

Captures what shipped live 2026-06-03 (enrichment rev 00039, signal-notifier
rev 00031) after a FRED VXVCLS/VIXCLS outage NULLed VIX3M for an entire
scan_date and wiped the signal slate (no trade that day).

- enrichment-trigger: _fetch_fred_csv retry (3x/30s, backoff) for VIX3M + VIX;
  on VIX3M failure, bounded carry-forward of the last non-null vix3m_at_enrich
  from BigQuery (<=7 calendar days, strictly < scan_date, else fail-closed).
  Bundled here with the parallel sector/industry persistence hunks (same file;
  NON-GATING).
- signal-notifier: live-VIX fallback FRED -> Stooq -> Yahoo with two-source
  corroboration (1.5 vol-pt agreement), plausibility bound, d<today guard, and
  vix_source provenance on todays_pick.
- docs: TRADING-STRATEGY regime-gate note; DECISIONS/2026-06-03-vix3m-fred-
  retry-and-carry-forward.md.
- research: premium_affordability_study.py (EV-neutral premium-cap finding).
- .gitignore: ignore the regenerable realized_label.pkl artifact.

gammarips-review: GO on both change sets (no lookahead — carry-forward reads
strictly < scan_date; sector is gating-inert; ALTER is idempotent).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Pre-existing SEO tooling, committed to clean the working tree. Read-only
analytics helpers (Google Search Console + GA4) under scripts/seo/ and the
gammarips-seo subagent definition. No secrets; .venv and __pycache__ ignored.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ades

Publishes the per-trade V5.4 cohort to Firestore ledger_trades/{scan_date}_{ticker}
for the public scorecard ledger table. Same cohort filter + fixed-dollar sizing
as cohort_stats/current, so the table rows and aggregate tiles can never disagree.

- compute_and_write_ledger_trades(): reads closed V5.4 forward_paper_ledger rows
  (V5_4_AGENT_RANKER, entry >= LIVE_COHORT_START_DATE, realized), parses the OCC
  contract (_parse_occ_contract) into option_type/strike/expiration, writes one
  idempotent Firestore doc per trade. Non-fatal; never raises into the email path.
- Called alongside compute_and_write_cohort_stats in run_notifier + /refresh_stats.
- DATA-CONTRACTS.md: ledger_trades collection schema.

Live (signal-notifier rev 00032); /refresh_stats backfilled all 6 closed trades.
gammarips-review: SAFE TO DEPLOY (read-only publish; cohort/sizing parity verified;
no gate/trader impact).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Inject a curated, leakage-safe forensic case-memory into the V5.4 Picker so it
reasons by analogy over past option winners/losers. Direct fenced-block
injection (the house pattern), NOT ADK MemoryService (session-recall RAG).

- build_case_memory.py (read-only): join realized_label.pkl (FILLED option
  outcome + underlying path) with overnight_signals_enriched (greeks/IV/catalyst)
  on (recommended_contract, scan_date); overlay 6 matched live ledger closes.
  Emits case_memory/{bull.md 846, bear.md 529, exemplars.md ~50 curated,
  build_manifest.json, case_index.parquet}.
- Outcome keyed on realized_ret>0 (option PnL) NOT is_win (stock direction) —
  they disagree 44.2%. WHY is deterministic option physics (theta drag / delta
  capture / inferred IV residual); no LLM-authored cause.
- quant.md: 12 hand-authored ledger-independent priors (Q1-Q12).
- Wire: {case_memory_block} in _build_picker_instruction; picker_v5.md adds a
  "how to use case memory" section; Dockerfile ships case_memory/;
  PICKER_PROMPT_VERSION=5.
- Fail CLOSED if v5 ships without the block (no silent v4 degrade);
  RankResponse.case_memory_bytes for observability; deploy.sh preflight assert.

Audited by gammarips-review (SHIP-WITH-FIXES, all fixed). Same-ticker
outcome-import documented as accepted+bounded. Advisory/non-gating; owner
waived N>=15/30-day-OOS ceremony, leakage was not waived.

Decision: docs/DECISIONS/2026-06-03-picker-case-memory.md

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The 2026-06-03 fix required TWO public sources (Stooq+Yahoo) to corroborate
within 1.5 vol-pts before trusting a live VIX when FRED is down. FRED was still
timing out on 2026-06-04; only Yahoo answered (16.06) so the rule rejected it
and the regime gate fail-closed — wiping scan 2026-06-03 (4 candidates, vix3m
carry-forward 18.66, plainly contango).

Drop the corroboration requirement: use the best public source that answers;
when both answer take the MAX (conservative for the one-sided vix_now>vix3m=>skip
gate — a low-biased source can't manufacture a false trade). Single source is
sufficient; only a total blackout fail-closes. Remove VIX_FALLBACK_TOLERANCE.

Lookahead-safe: every fallback bar still passes _vix_date_ok (d<=scan_date AND
d<today). gammarips-review: GO. Deployed signal-notifier-00033-sjr; re-ran scan
2026-06-03 -> BBWI BULLISH emailed before the 10:00 ET entry.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…e fix

The 2026-06-02..04 "FRED outage" was self-inflicted. Our fredgraph.csv requests
carried no start date, so FRED serialized each series' full history back to 1990
on every call — a payload that now exceeds the read timeout every morning. The
retries couldn't help (each re-requests the same giant dump) and the carry-forward
/ two-source / Yahoo fallbacks only fired because the primary always timed out.

Proven by live probe: bare ?id=VIXCLS times out at 30s deterministically;
?id=VIXCLS&cosd=<date> returns HTTP 200 in ~2s. Same for VXVCLS.

Bound every FRED CSV fetch with cosd (start date) = scan_date/target_date − N days:
- enrichment-trigger: _fred_csv_url() helper + FRED_CSV_LOOKBACK_DAYS=45 (VXVCLS
  gate + VIXCLS context); unparseable-date falls back to unbounded URL.
- signal-notifier: cosd inlined in fetch_vix_close (live VIX leg, 45d).
- forward-paper-trader: _fetch_vix_daily_fred(target_date) bounded 60d, 15s→30s
  timeout (telemetry-only, non-blocking).

Parse helpers unchanged — still take the latest close on/before scan_date, so cosd
only moves the window START earlier (lookahead-safe). gammarips-review: GO on all
three services. Retry/carry-forward/source-fallback retained as defense-in-depth.

Revs: enrichment-trigger-00041-trm, signal-notifier-00034-ds9,
forward-paper-trader-00037-t65.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…e (judge_v6)

Replace the two-stage V5.4 ranker (per-candidate Scorer fanout + Picker) with a
single memory-aware judge: one structured gemini-3.1-pro-preview call scores every
gate-cleared candidate AND selects the pick. Rename service+dir+code signal-ranker
→ signal-judge (BQ table signal_ranker_runs + Firestore v5_4_* keys intentionally
kept — migration/webapp landmines, no payoff).

Why: post-gate slates are mostly ≤5 candidates, so the Scorer's top-5 cut was a
no-op ~80% of days; ITM/earnings/spread rules were triple-encoded (gates + scorer +
picker). A 13-slate replay (workflow) showed the single judge agreed 9/13 with the
2-stage baseline and was structurally sounder 4-to-1 on divergences (each was the
judge rejecting a two-label-trap the 2-stage took). gammarips-review: SHIP. Live
gemini smoke on the 2026-06-03 slate reproduced the BBWI pick with anti-anchoring.

- judge_v6.md: trusts upstream gates, anti-anchoring ("score as if only candidate"),
  per-candidate verdict array, mass-leakage skip, deterministic composite/tiebreak.
- JudgeOutput/PerCandidateVerdict schemas; ScorerOutput/PickerOutput kept for replay.
- run_judge: leakage-assert all candidates → ONE structured call → JUDGE_MAX_ATTEMPTS=3
  bounded retry (replaces the lost MIN_SCORER_SUCCESS_FRAC partial-failure tolerance).
- persist_run: one row per verdict; judge mirrored into both scorer/picker REQUIRED
  columns at version=6 → BQ DDL unchanged, cohort cleanly separable.
- Wire contract preserved → signal-notifier needs no logic change (only repointed
  SIGNAL_RANKER_URL → SIGNAL_JUDGE_URL at the new service).
- Docs: TRADING-STRATEGY, CLAUDE.md + GEMINI.MD, CHEAT-SHEET, decision note.

Deployed: signal-judge-00001-4kn (DRY_RUN=false), signal-notifier-00035-bvh repointed.
Old signal-ranker kept live as rollback. 32 unit tests pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
V/OI>2 was removed as a gate 2026-06-02 (no realized-PnL selection value).
Update the gate list the blog writer cites + spread 10%→8% so future posts
don't describe V/OI as a gate.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ame + V/OI removal

Durable-handoff pass over the authoritative/living docs (historical DECISIONS/
EXEC-PLANS left as the record):

- MODELS.md: registry now shows gemini-3.1-pro-preview as the single signal-judge
  judge_v6 (scores + selects in one call); gemini-3.5-flash no longer powers any
  judge stage (Scorer removed). Env-swap table + cohort-attribution note updated
  (segment by scorer_prompt_version: 5=two-stage, 6=judge_v6).
- ARCHITECTURE.md: added signal-judge + signal-notifier service entries (the map
  previously jumped enrichment → trader); fixed the data-flow gate stack.
- DATA-CONTRACTS.md: policy-contract gates corrected (spread 0.08, moneyness
  5-13%, V/OI gate removed) + judge/rename note; moneyness field 5-15% → 5-13%.
- GLOSSARY.md: added signal-judge row; signal-notifier row de-stale'd.
- TRADING-STRATEGY.md / CHEAT-SHEET.md: residual Scorer/Picker/signal-ranker
  mentions → single judge_v6 / signal-judge; SLO + fallback + skip-reason copy.
- TESTING.md: enrichment spread 0.10 → 0.08.

Kept deliberately: signal_ranker_runs table name, Firestore v5_4_* keys, the
V5_4_AGENT_RANKER policy_version label. Not touched: the broader Agent-Arena
"5-model debate" narrative (separate webapp/marketing pass).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ignals

signal-judge now runs a randomized bracket tournament (tournament_v1, version 7)
instead of the single judge_v6 call, and signal-notifier ungates the candidate
pool so every enriched signal gets a chance.

Why: the gated single judge over-fit junk (picked score-2 BBWI over $100M-flow
names) and the selection/liquidity gates were choking real winners on stale
scan-time OI (the sweep only becomes OI the next morning; we enter at 10:00 and
ride the build). Features barely separate winners from losers (EV ~flat), so a
rigid scorer can't extract edge that isn't there — a simple prompt over the full
pool at least picks sensible, report-aligned trades.

signal-judge (app/agent.py): 3 independent brackets; each shuffles the pool,
batches of <=10, top-2 advance (top-1 in the final batch) until one remains
(94->20->4->1); consensus across the 3 = pick (3/3 high, 2/3 medium, 1/3 low).
Dead-simple prompt + daily report + per-contract JSON. No memory, no rubric.
assert_no_leakage on every candidate; fail-closed on no winner.

signal-notifier (main.py): candidate query ungated (moneyness/OI/vol/DTE/V-OI
removed, LIMIT 200) + rich feature columns added (no outcome cols); active-days
liquidity gate BYPASSED (also drops ~N Polygon calls). KEPT: no-earnings-in-hold
and regime fail-closed (safety, not selection). /rank + service timeouts bumped
for the longer tournament.

persist: tournament has no rubric scores -> advancement proxy (round reached ->
1-10) into the REQUIRED columns, version 7, finalists+winner+runner_up only. BQ
DDL unchanged; cohort separable (5=two-stage, 6=judge_v6, 7=tournament).

gammarips-review (leakage): SHIP — no forward column can reach the model (60-col
allowlist + assert_no_leakage catches all 10 outcome cols). Deployed signal-judge
+ signal-notifier-00036-c6t; live /rank on 94 candidates verified (MSFT, medium,
version=7 rows persisted). See docs/DECISIONS/2026-06-04-bracket-tournament.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
V5.4 (gated single-judge) was a dud — 13 live closes, avg 0.0%. Owner-directed
clean break: wipe the ledger and start the tournament cohort fresh as V6.

- forward_paper_ledger TRUNCATED (13 V5.4 rows; dumped to .scratch as insurance).
- policy_version V5_4_AGENT_RANKER -> V6_TOURNAMENT across all WRITE sites
  (forward-paper-trader POLICY_VERSION constant; signal-notifier todays_pick +
  ledger_trades writes) and all READ-FILTERS (signal-notifier cohort_stats + 14d
  summary, win-tracker, x-poster, blog-generator) so the app surfaces V6 not blank.
- LIVE_COHORT_START_DATE -> 2026-06-04; cohort_stats/current refreshed -> V6, 0 trades.
- webapp cohort-stats default -> V6 (committed separately in gammarips-webapp).

Deployed: forward-paper-trader-00038-fd5, signal-notifier-00038-7wx.
win-tracker/x-poster/blog code updated but NOT redeployed (harmless — V5.4 gone,
no V6 closes yet; deploy before first V6 close surfaces).

CLAUDE.md policy summary rewritten for V6. See
docs/DECISIONS/2026-06-04-bracket-tournament.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
_best_contract scored contracts with a `vol/max(oi,1)` term that REWARDED low
open interest as "unusual" — so it picked the swept lottery strike (OKTA $127
6/12: OI 5, ~35% live spread, untradeable) over the standard liquid strike (OKTA
$130: OI 48, fillable). Unusual flow is the right signal for the NAME+direction;
using it to pick the CONTRACT hands you the strike you can't fill.

Rewrite the score: open interest PRIMARY (5x, accumulates, can't be faked by one
sweep), volume secondary (2x), snapshot spread tertiary (1.5x — it read 0.5% on
that 35%-wide OKTA strike, so it's noisy), keep sweet-spot delta + gamma (de-
emphasized 20x->8x) + theta penalty. Flips OKTA to $130.

No hard OI floor (scan OI is stale; a fresh sweep that builds reads ~0 — don't
reject those). Live fillability check at pick time is the next, separate layer.

Deployed overnight-scanner-00010-jk2; takes effect next overnight scan.
See docs/DECISIONS/2026-06-04-contract-selection-liquidity.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adversarial multi-agent audit (every finding re-verified vs code+BQ data) found
16 silent bugs. 13 fixed; 3 deferred (need PIT data/schema). Trigger: OKTA $127
untradeable-ghost pick.

CRITICAL #1 (root cause): polygon_client stopped substituting day low/high for a
missing bid/ask — that produced fake/0% spreads on ~43% of picks (718/1815 = 0.0),
defeating the spread gate and feeding the judge "0.5% spread" ghosts. Missing quote
-> NULL spread; chosen contract now carries a real spread. Enrichment spread gate
loosened 0.08->0.30 (was filtering fake 0s; real spreads are wider).

HIGH #2: divergence flip resolves BEFORE conviction sub-scores (was scoring flipped
names on the abandoned side -> ~87% suppressed below MIN_SCORE). #5: judge prompt
strips still-stale volume/OI/V-OI (keeps now-real spread). #8: technicals window
bounded to scan_date not date.today() (was leaking next-day bars = lookahead).
#6/#7/#10: signal-notifier fallback moneyness band restored + dead gates/docs cleaned.

MED #9/#12/#13: trader symmetric slippage + stale-TIMEOUT + late-fill guards (removed
EV-optimism). #11: empty judge batch re-queues instead of dropping 10 candidates.
#14: in_top_5 is a real top-5. LOW #15: overnight_score fail-safe default. #16:
greeks store raw with None preserved (delta no longer NULL->0.0).

Deferred (separate pass): #3 OI frozen-snapshot, #4 volume frozen-cumulative (need
Polygon flat files / day-bars), #15-full (schema add). See
docs/DECISIONS/2026-06-04-pipeline-bug-fixes.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Make the scaffold tell the truth — no V5.4/judge_v6/Scorer-Picker/case-memory as
the live description anywhere; historical DECISIONS/EXEC-PLANS left as the record.

- CLAUDE.md + .gemini/GEMINI.MD (lockstep): policy summary = V6 tournament; spread
  gate 8%->0.30; blog-generator marked DEPLOYED; bug-hunt summary added.
- CHEAT-SHEET.md: retitled "V6 Tournament"; gate list + pick section rewritten.
- docs/TRADING-STRATEGY.md: Status/regime/filter-stack/policy_version -> V6.
- docs/MODELS.md: registry -> tournament_v1 judge; no Scorer/Picker; cohort 5/6/7.
- docs/ARCHITECTURE.md + GLOSSARY.md: signal-judge/notifier/trader + spread 0.30.
- docs/DATA-CONTRACTS.md: V6 policy contract + field-quality caveats + new cols.
- NEXT_SESSION_PROMPT.md: bug-hunt handoff + the has_contract WATCH.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…he-data lesson

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The blog-generator's BQ filters were already V6_TOURNAMENT, but its
prompt/forbidden-list NARRATIVE was two eras stale — it would re-draft
V5.4 / Agent Arena / "gate stack" / "5-13% OTM moneyness" / "9:00 AM"
content on the next weekly cron (Mon 05:00 ET) and on any /generate regen.

- agent.py (writer forbidden-list): current floor is score>=4, alert is
  7:30 AM ET; add Agent Arena / Scorer / Picker / gate stack / 5-13% OTM
  moneyness to the retired list.
- fast_api_app.py: newsletter retired-concepts list (add V5.4 / Arena /
  Scorer / Picker / gate stack / moneyness); reddit lead_style + algotrading
  mod_traps drop "gate stack" → tournament/bracket; reddit topic list rewritten
  to the V6 enrichment bar + 2 safety rails + "no selection gates" (was the
  full V5.4 moneyness/spread/V-OI gate list).
- tools.py / voice_rules.py: stale V5.4/V3-V4 comments + the X-poster
  "V5.4 cohort >= 30 closes" do-not rule → V6.

Shared voice_rules.py is vendored into x-poster too, so this also de-stales
X copy. Not deployed — engine code only.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Alert time moved to 07:30 ET (was 9:00 AM). Update the blog_schedule slot
title_candidate + keyword so /generate re-drafts an honest title; the live
blog_schedule/current row was updated to match. The /9am slug stays (URL
artifact only). Post regenerated clean on V6 (reviewer 10.0).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant